
package com.gitee.jmash.rbac.dao;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import com.gitee.jmash.common.utils.UUIDUtil;
import com.gitee.jmash.core.orm.DtoPage;
import com.gitee.jmash.core.orm.DtoTotal;
import com.gitee.jmash.core.orm.jpa.BaseDao;
import com.gitee.jmash.core.orm.jpa.SqlBuilder;
import com.gitee.jmash.core.orm.jpa.TenantEntityManager;
import com.gitee.jmash.rbac.entity.PermEntity;
import jmash.rbac.protobuf.PermReq;

/**
 * Perm实体的Dao层（使用JPA实现）.
 *
 * @author <a href="mailto:service@crenjoy.com">crenjoy</a>
 */
public class PermDao extends BaseDao<PermEntity, UUID> {

  public PermDao() {
    super();
  }

  public PermDao(TenantEntityManager tem) {
    super(tem);
  }

  /** 通过权限编码查询权限. */
  public PermEntity findByCode(String code) {
    return this.findSingle("select s from PermEntity s where s.permCode = ?1 ", code);
  }

  /** 获取角色拥有的权限 */
  public List<String> findRolePerms(UUID roleId) {
    String sql =
        "select distinct p.permCode from PermEntity p where EXISTS ( select 1 from RolesPermsEntity s where s.roleId = ?1 and  s.permId = p.permId ) ";
    return this.findList(sql, String.class, roleId);
  }

  /** 权限编码转化为ID. */
  public Set<UUID> codesToIds(List<String> permCodes) {
    if (permCodes.isEmpty()) {
      return Collections.emptySet();
    }
    Map<String, UUID> map = findCodeIdMap(PermReq.newBuilder().build());
    Set<UUID> ids = new HashSet<UUID>();
    for (String permCode : permCodes) {
      if (map.containsKey(permCode)) {
        ids.add(map.get(permCode));
      }
    }
    return ids;
  }

  /** 获取权限Code,Id Map. */
  public Map<String, UUID> findCodeIdMap(PermReq req) {
    List<PermEntity> list = findListByReq(req);
    return list.stream().collect(
        Collectors.toMap(PermEntity::getPermCode, PermEntity::getPermId, (key1, key2) -> key1));
  }
  
  /** 获取权限Code,PermEntity Map. */
  public Map<String, PermEntity> findMapByReq(PermReq req) {
    List<PermEntity> list = findListByReq(req);
    return list.stream().collect(
        Collectors.toMap(PermEntity::getPermCode, perm -> perm, (key1, key2) -> key1));
  }


  /** 通过操作编码查询权限. */
  public List<PermEntity> findByOperationCode(String operationCode) {
    String sql = "select s from PermEntity s where s.permCode like ?1";
    return this.findList(sql, PermEntity.class, "%"+operationCode);
  }

  /**
   * 综合查询.
   */
  public List<PermEntity> findListByReq(PermReq req) {
    SqlBuilder sqlBuilder = createSql(req);
    String query = sqlBuilder.getQuerySql("select s ");
    return this.findListByParams(query, sqlBuilder.getParams());
  }

  /**
   * 综合查询Page.
   */
  public DtoPage<PermEntity, DtoTotal> findPageByReq(PermReq req) {
    SqlBuilder sqlBuilder = createSql(req);
    String query = sqlBuilder.getQuerySql("select s ");
    String totalQuery = sqlBuilder.getTotalSql("select count(s) as totalSize ");
    return this.findDtoPageByParams(req.getCurPage(), req.getPageSize(), query, totalQuery,
        DtoTotal.class, sqlBuilder.getParams());
  }

  /** Create SQL By Req . */
  public SqlBuilder createSql(PermReq req) {
    StringBuilder sql = new StringBuilder(" from PermEntity s where 1=1  ");
    Map<String, Object> params = new HashMap<String, Object>();

    if (StringUtils.isNotBlank(req.getRoleId())) {
      sql.append(" and exists ( select p.permId from RolesPermsEntity p where "
          + "s.permId = p.permId and p.roleId = :roleId ) ");
      params.put("roleId", UUIDUtil.fromString(req.getRoleId()));
    }

    if (StringUtils.isNotBlank(req.getLikePermCode())) {
      sql.append(" and s.permCode like :likePermCode ");
      params.put("likePermCode", "%" + req.getLikePermCode() + "%");
    }

    if (StringUtils.isNotBlank(req.getLikePermName())) {
      sql.append(" and s.permName like :likePermName ");
      params.put("likePermName", "%" + req.getLikePermName() + "%");
    }

    String orderSql = " order by s.permCode asc";
    if (StringUtils.isNotBlank(req.getOrderName())) {
      orderSql = String.format(" order by %s %s ", req.getOrderName(),
          req.getOrderAsc() ? " asc " : " desc ");
    }

    return SqlBuilder.build().setSql(sql).setParams(params).setOrderSql(orderSql);
  }

}
